package com.fengshang.wedding.domain.service.internal;

import java.util.Collection;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import com.fengshang.wedding.domain.Constants;

/**
 * 
 *@author gembin@gmail.com
 * 
 */
@SuppressWarnings("unchecked")
public abstract class AbstractPersistenceService<T> implements Constants {
	
	private EntityManager entityManager;

	@PersistenceContext(unitName = "weddingPU")
	public void setEntityManager(EntityManager em) {
		this.entityManager = em;
	}
	/**
	 * @return EntityManager
	 */
	public EntityManager getEntityManager() {
		return entityManager;
	}
	/**
	 * entity name which supposes to be override by subclasses
	 */
	public abstract String entityName();
	/**
	 * @param property
	 * @param value
	 * @return
	 */
	public T findBy(Object property,Object value){
		Query q=entityManager.createQuery("SELECT e FROM "+entityName()+" e WHERE e."+property+"=?1");
		q.setParameter(1, value);
		return (T) q.getSingleResult();
	}
	/**
	 * @param t
	 * @param id
	 * @return
	 */
	public T findById(Class<T>t,int id){
		return entityManager.find(t, id);
	}
	/**
	 * 
	 * @param entity
	 * @return
	 */
	public T update(Object entity){
		return (T) entityManager.merge(entity);
	}
	/**
	 * @param entity
	 */
	public void save(Object entity){
		entityManager.persist(entity);
	}
	/**
	 * @param t
	 * @param id
	 */
	public void remove(Class t,int id){
		Object entity=entityManager.find(t, id);
		if(entity==null)
			throw new EntityNotFoundException("Entity["+t.getName()+"] with id="+id+" dose not exists!");
		  entityManager.remove(entity);
	}
	/**
	 * @return Total Records
	 */
	public int getTotalRecords(){
		int total = ((Long)entityManager.createQuery("SELECT COUNT(e) FROM "+entityName()+" e").getSingleResult()).intValue();
		return total;
	}
	/**
	 * 
	 * @return
	 */
	public int getEntityTotalPages(){
		return getEntityTotalPages(0);
	}
	
	/**
	 * 
	 * @param pageSize
	 * @return
	 */
	public int getEntityTotalPages(int pageSize){
		int total = ((Long)entityManager.createQuery("SELECT COUNT(e) FROM "+entityName()+" e").getSingleResult()).intValue();
		if(pageSize<=0)
			pageSize=DEFAULT_PAGE_SIZE;
		int pages=0;
		if(total==0)return 0;
		if(total<=pageSize)return 1;
		if(total%pageSize==0)return (pages=total/pageSize);
		return pages+1;
	}
	/**
	 * use native SQL or JPQL
	 * @param isNativeQuery
	 * @param query
	 * @param pageSize
	 * @param currentPage
	 * @return
	 */
	public Collection<T> findByPagination(boolean isNativeQuery,String query,
			int pageSize, int currentPage) {
		if (pageSize <= 0) {
			pageSize = DEFAULT_PAGE_SIZE;
		}
		if (currentPage <= 0) {
			currentPage = 1;
		}
		Query q;
		if(isNativeQuery){
			q=entityManager.createNativeQuery(query==null?"SELECT * FROM "+entityName():query);
		}else{
			q=entityManager.createQuery(query==null?"SELECT e FROM "+entityName()+" e":query);
		}
		return q.setFirstResult(pageSize*(currentPage-1))
		.setMaxResults(pageSize * currentPage)
		.getResultList();
	}

}
